package com.zenithmind.user.controller;

import com.zenithmind.common.annotation.Log;
import com.zenithmind.common.constant.OperationTypeEnum;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.result.Result;
import com.zenithmind.user.pojo.domain.VerificationCode;
import com.zenithmind.user.pojo.dto.VerificationRequestDTO;
import com.zenithmind.user.pojo.query.VerificationCodeQuery;
import com.zenithmind.user.pojo.vo.VerificationCodeVO;
import com.zenithmind.user.service.UserService;
import com.zenithmind.user.service.VerificationCodeService;
import com.zenithmind.user.service.impl.VerificationCodeServiceImpl;
import com.zenithmind.user.enums.VerificationCodeType;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import org.springframework.validation.annotation.Validated;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zenithmind.user.pojo.domain.User;
import com.zenithmind.user.mapper.UserMapper;
import com.zenithmind.common.result.ResultCode;

import java.util.List;
import java.util.Map;
import java.util.HashMap;

/**
 * 验证码管理控制器
 */
@Slf4j
@RestController
@RequestMapping("/api/zenithMind/verification")
@Tag(name = "验证码管理")
@Validated // For validating request parameters like @Email
public class VerificationCodeController {

    private static final Logger logger = LoggerFactory.getLogger(VerificationCodeController.class);

    @Autowired
    private VerificationCodeService verificationCodeService;
    
    @Autowired
    private VerificationCodeServiceImpl verificationCodeServiceImpl;
    
    @Autowired
    private UserService userService;

    @Autowired
    private UserMapper userMapper;

    /**
     * 生成验证码
     *
     * @param verificationRequestDTO 验证码请求DTO
     * @param request HTTP请求，用于获取IP地址
     * @return 生成结果
     */
    @Log(description = "生成验证码", operationType = OperationTypeEnum.ADD)
    @PostMapping("/generateVerificationCode")
    @Operation(summary = "生成验证码")
    public Result<Void> generateCode(
            @RequestBody VerificationRequestDTO verificationRequestDTO,
            HttpServletRequest request) {
        logger.info("生成验证码请求: 用户名={}, 邮箱={}", 
                verificationRequestDTO.getUsername(), 
                verificationCodeServiceImpl.maskEmail(verificationRequestDTO.getEmail()));
                
        verificationCodeServiceImpl.generateCode(verificationRequestDTO, request);
        
        return Result.success();
    }
    
    /**
     * 发送登录验证码接口 (通用)
     *
     * @param verificationRequestDTO 验证码请求DTO
     * @return 发送结果
     */
    @Log(description = "发送登录验证码", operationType = OperationTypeEnum.ADD)
    @GetMapping("/sendLoginVerificationCode")
    @Operation(summary = "发送登录验证码 (通用)")
    public Result<Void> sendLoginVerificationCode(@ModelAttribute VerificationRequestDTO verificationRequestDTO) {
        logger.info("发送登录验证码请求: 用户名={}", verificationRequestDTO.getUsername());
        return verificationCodeService.sendLoginVerificationCode(verificationRequestDTO);
    }

    /**
     * 验证验证码
     *
     * @param verificationRequestDTO 验证码请求DTO
     * @return 验证结果
     */
    @Log(description = "验证验证码", operationType = OperationTypeEnum.QUERY)
    @PostMapping("/verifyVerificationCode")
    @Operation(summary = "验证验证码")
    public Result<Boolean> verifyCode(@RequestBody VerificationRequestDTO verificationRequestDTO) {
        logger.info("验证验证码请求: 用户名={}", verificationRequestDTO.getUsername());
        boolean success = verificationCodeService.verifyCode(verificationRequestDTO);
        
        return Result.success(success);
    }

    /**
     * 设置验证码类型
     *
     * @param verificationRequestDTO 验证码请求DTO
     * @return 设置结果
     */
    @Log(description = "设置验证码类型", operationType = OperationTypeEnum.UPDATE)
    @PostMapping("/setVerificationCodeType")
    @Operation(summary = "设置验证码类型")
    public Result<Boolean> setCodeType(@RequestBody VerificationRequestDTO verificationRequestDTO) {
        logger.info("设置验证码类型请求: 用户名={}, 类型={}", 
                verificationRequestDTO.getUsername(), 
                verificationRequestDTO.getType());
        boolean success = verificationCodeService.setCodeType(verificationRequestDTO);
        
        return Result.success(success);
    }

    /**
     * 查询用户验证码历史
     *
     * @param verificationRequestDTO 验证码请求DTO
     * @return 验证码记录列表
     */
    @Log(description = "查询用户验证码历史", operationType = OperationTypeEnum.QUERY)
    @GetMapping("/getVerificationHistory")
    @Operation(summary = "查询用户验证码历史")
    public Result<List<VerificationCode>> getUserVerificationHistory(
            @ModelAttribute VerificationRequestDTO verificationRequestDTO) {
        logger.info("查询验证码历史: 用户名={}, 数量={}", 
                verificationRequestDTO.getUsername(), 
                verificationRequestDTO.getLimit());
        List<VerificationCode> history = verificationCodeService.getUserVerificationHistory(verificationRequestDTO);
        return Result.success(history);
    }

    /**
     * 手动清理过期验证码
     *
     * @return 清理结果
     */
    @Log(description = "清理过期验证码", operationType = OperationTypeEnum.DELETE)
    @PostMapping("/cleanExpiredVerificationCodes")
    @Operation(summary = "手动清理过期验证码")
    public Result<Map<String, Object>> cleanExpiredCodes() {
        logger.info("手动清理过期验证码请求");
        int count = verificationCodeService.cleanExpiredCodes();
        
        Map<String, Object> result = new HashMap<>();
        result.put("count", count);
        result.put("message", "清理了" + count + "条过期验证码");
        
        return Result.success(result);
    }
    
    /**
     * 分页查询验证码记录
     *
     * @param verificationCodeQuery 验证码查询条件，包含分页信息和查询条件
     * @return 分页验证码记录
     */
    @Log(description = "分页查询验证码记录", operationType = OperationTypeEnum.QUERY)
    @GetMapping("/pageVerificationCodes")
    @Operation(summary = "后台管理-分页查询验证码记录")
    public Result<PageResult<VerificationCodeVO>> pageVerificationCodes(VerificationCodeQuery verificationCodeQuery) {
        logger.info("分页查询验证码记录: 页码={}, 每页={}, 用户名={}, 类型={}, 已验证={}", 
                verificationCodeQuery.getCurrent(), verificationCodeQuery.getSize(),
                verificationCodeQuery.getUsername(), verificationCodeQuery.getType(), 
                verificationCodeQuery.getVerified());
        
        PageResult<VerificationCodeVO> result = verificationCodeService.pageVerificationCodes(verificationCodeQuery);
        return Result.success(result);
    }
    
    /**
     * 根据ID获取验证码详情
     *
     * @param id 验证码ID
     * @return 验证码详情
     */
    @Log(description = "查询验证码详情", operationType = OperationTypeEnum.QUERY)
    @GetMapping("/getVerificationCodeById/{id}")
    @Operation(summary = "获取验证码详情")
    public Result<VerificationCode> getVerificationCodeById(@PathVariable @Parameter(description = "验证码ID") Long id) {
        logger.info("查询验证码详情: ID={}", id);
        VerificationCode verificationCode = verificationCodeService.getById(id);
        return Result.success(verificationCode);
    }
    
    /**
     * 更新验证码记录
     *
     * @param id 验证码ID
     * @param verificationCode 验证码信息
     * @return 更新结果
     */
    @Log(description = "更新验证码记录", operationType = OperationTypeEnum.UPDATE)
    @PutMapping("/updateVerificationCode/{id}")
    @Operation(summary = "更新验证码记录")
    public Result<Boolean> updateVerificationCode(
            @PathVariable @Parameter(description = "验证码ID") Long id,
            @RequestBody VerificationCode verificationCode) {
        verificationCode.setId(String.valueOf(id));
        logger.info("更新验证码记录: ID={}", id);
        boolean success = verificationCodeService.updateById(verificationCode);
        return Result.success(success);
    }
    
    /**
     * 删除验证码记录
     *
     * @param id 验证码ID
     * @return 删除结果
     */
    @Log(description = "删除验证码记录", operationType = OperationTypeEnum.DELETE)
    @DeleteMapping("/deleteVerificationCode/{id}")
    @Operation(summary = "删除验证码记录")
    public Result<Boolean> deleteVerificationCode(@PathVariable @Parameter(description = "验证码ID") Long id) {
        logger.info("删除验证码记录: ID={}", id);
        boolean success = verificationCodeService.removeById(id);
        return Result.success(success);
    }
    
    /**
     * 批量删除验证码记录
     *
     * @param ids 验证码ID列表
     * @return 删除结果
     */
    @Log(description = "批量删除验证码记录", operationType = OperationTypeEnum.DELETE)
    @DeleteMapping("/batchDeleteVerificationCodes")
    @Operation(summary = "批量删除验证码记录")
    public Result<Boolean> batchDeleteVerificationCodes(@RequestBody List<Long> ids) {
        logger.info("批量删除验证码记录: IDs={}", ids);
        boolean success = verificationCodeService.removeByIds(ids);
        return Result.success(success);
    }
    
    /**
     * 统计验证码使用情况
     *
     * @return 统计数据
     */
    @Log(description = "统计验证码使用情况", operationType = OperationTypeEnum.QUERY)
    @GetMapping("/getVerificationStatistics")
    @Operation(summary = "统计验证码使用情况")
    public Result<Object> getVerificationStatistics() {
        logger.info("统计验证码使用情况");
        Object statistics = verificationCodeService.getVerificationStatistics();
        return Result.success(statistics);
    }

    /**
     * 添加或更新验证码
     *
     * @param verificationCode 验证码信息
     * @return 更新结果
     */
    @Log(description = "添加或更新验证码", operationType = OperationTypeEnum.UPDATE)
    @PostMapping("/addOrUpdateVerificationCode")
    @Operation(summary = "添加或更新验证码")
    public Result<VerificationCode> addOrUpdateVerificationCode(@RequestBody VerificationCode verificationCode) {
        logger.info("添加或更新验证码: ID={}", verificationCode.getId());
        boolean success = verificationCodeService.saveOrUpdate(verificationCode);
        return Result.success(verificationCode);
    }
    
    /**
     * 发送注册验证码到邮箱
     *
     * @param email 邮箱地址
     * @param username 用户名（可选）
     * @return 发送结果
     */
    @Log(description = "发送注册验证码到邮箱", operationType = OperationTypeEnum.ADD)
    @GetMapping("/sendRegisterEmailCode")
    @Operation(summary = "发送注册验证码到邮箱")
    public Result<Void> sendRegisterEmailCode(
            @RequestParam @NotBlank @Email @Parameter(description = "邮箱地址", required = true) String email,
            @RequestParam(required = false) @Parameter(description = "用户名（可选）") String username) {
        // 验证邮箱是否已注册
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getEmail, email);
        if (userMapper.selectCount(wrapper) > 0) {
            return Result.fail(ResultCode.EMAIL_EXIST);
        }
        
        // 发送注册验证码
        VerificationRequestDTO verificationRequestDTO = new VerificationRequestDTO();
        verificationRequestDTO.setEmail(email);
        verificationRequestDTO.setUsername(username);
        verificationRequestDTO.setType(VerificationCodeType.REGISTRATION.getValue());
        
        // 调用正确的方法生成验证码
        verificationCodeService.generateCode(verificationRequestDTO);
        return Result.success();
    }
} 